package com.xquant.trade.trade.controller;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.github.pagehelper.PageInfo;
import com.xquant.common.core.web.controller.BaseController;
import com.xquant.common.core.web.page.TableDataInfo;
import com.xquant.common.security.utils.ExcelUtil;
import com.xquant.common.security.utils.SecurityUtils;
import com.xquant.trade.trade.entity.*;
import com.xquant.trade.trade.service.impl.DurationServiceImpl;
import com.xquant.trade.trade.service.impl.TradeServiceImpl;
import com.xquant.trade.utils.CommResponse;
import com.xquant.trade.utils.SysUtils;
import com.xquant.trade.utils.TransferUtil;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Map;

/**
 * newCloud
 *
 * @author:xQuant
 * @description:交易管理
 * @title:交易管理
 */
@RestController
@RequestMapping("trade")
public class TradeController extends BaseController {

    @Autowired
    private TradeServiceImpl tradeService;

    @Autowired
    private DurationServiceImpl durationService;

    /**
     * newCloud controller 查询场内交易
     *
     * @param params
     * @return
     */
    @RequestMapping(value = "/querySimpleTradeByPage.action")
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:list')")
    TableDataInfo querySimpleTradeByPage(@RequestParam Map params) {
        startPage();
        List<InnerTrade> list = tradeService.querySimpleTradeByPage(params);
        return getDataTable(list);
    }

    /**
     * newCloud controller 查询场内持仓
     *
     * @param params
     * @return
     */
    @RequestMapping(value = "/querysimpleTradeGroup.action")
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:group')")
    CommResponse querysimpleTradeGroup(@RequestParam Map params) {
        params.put("userId", SecurityUtils.getUserId());
        List list = tradeService.querysimpleTradeGroup(params);
        CommResponse res = new CommResponse(true, "success", list);
        return res;
    }

    // 导出分组的场内交易  场内持仓
    @RequestMapping(value = "/exportSimpleTradeGroup.action")
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:groupExport')")
    void exportsimpleTradeGroup(HttpServletResponse response, @RequestParam Map params) {
        startPage();
        params.put("userId", SecurityUtils.getUserId());
        List list = tradeService.querysimpleTradeGroup(params);
        ExcelUtil<TradeGroupDTO> util = new ExcelUtil<TradeGroupDTO>(TradeGroupDTO.class);
        util.exportExcel(response, list, "场内交易持仓");
    }

    /**
     * 查询场外期权交易列表包含场内交易  场外持仓
     */
    @PreAuthorize("@ss.hasPermi('trade:tradebalance:list')")
    @RequestMapping(value = "/queryTrade4OtcOptionByPage.action")
    TableDataInfo queryTrade4OtcOptionByPage(@RequestParam Map map) {
        startPage();

        if (StrUtil.isNotBlank(MapUtils.getString(map, "duEventStatus"))) {
            if (JSONUtil.parseArray(MapUtils.getString(map, "duEventStatus")).size() > 0) {
                map.put("duEventStatus", JSONUtil.parseArray(MapUtils.getString(map, "duEventStatus")).toArray(String.class));
            } else {
                map.put("duEventStatus", null);
            }
        }

        if (StrUtil.isNotBlank(MapUtils.getString(map, "productTypes"))) {
            if (JSONUtil.parseArray(MapUtils.getString(map, "productTypes")).size() > 0) {
                map.put("productTypes", JSONUtil.parseArray(MapUtils.getString(map, "productTypes")).toArray(String.class));
            }else {
                map.put("productTypes", null);
            }
        }

        map.put("userId", SecurityUtils.getUserId());

        List<Trade> list = tradeService.queryTradeDuration4OtcOptionByPage(map);

        return getDataTable(list);
    }

    /**
     * 查询场外期权交易列表 期权簿记
     */
    @PreAuthorize("@ss.hasPermi('trade:tradebalance:list')")
    @RequestMapping(value = "/queryTradeOption4OtcOptionByPage.action")
    TableDataInfo queryTradeOption4OtcOptionByPage(@RequestParam Map map) {
        startPage();
        List<Trade> list = tradeService.queryTradeDuration4OtcOptionByPage(map);
        return getDataTable(list);
    }

    /**
     * 查询组合持仓列表 有权限控制
     */
    @RequestMapping(value = "/queryGroupBalanceByPage.action")
    @PreAuthorize("@ss.hasPermi('risk:profitmanage:tradeprofit:list')")
    PageInfo<Trade> queryGroupBalanceByPage(@RequestParam Map map) {
        startPage();
        PageInfo<Trade> pageInfo = tradeService.queryGroupBalanceByPage(map);
        return pageInfo;
    }

    /**
     * 检查交易信息
     */
    @RequestMapping(value = "/checkTradeDate.action")
    public CommResponse checkTradeDate(@RequestBody Trade trade) {

        return CommResponse.success();
    }

    /**
     * 新增交易
     */
    @RequestMapping(value = "/insertTrade.action")
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:insert')")
    CommResponse insertTrade(@RequestBody Trade trade) {
        CommResponse commResponse = new CommResponse(true);
        try {

            commResponse = tradeService.insertTrade(trade);

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return commResponse;
    }

    /**
     * 修改交易
     */
    @RequestMapping(value = "/updateTrade.action")
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:update')")
    CommResponse updateTrade(@RequestBody Trade trade) {
        CommResponse commResponse = new CommResponse(true);
        if (trade.getCalcInstrumentForm() != null) {
            trade.setPrice(trade.getCalcInstrumentForm().getSpotPrice());
        }
        commResponse=tradeService.updateTrade(trade);
        return commResponse;
    }

    /**
     * 删除交易
     */
    @RequestMapping(value = "/deleteTrade.action")
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:delete')")
    CommResponse deleteTrade(@RequestBody Trade trade) {
        return tradeService.deleteTrade(trade);
    }

    /**
     * 导出期权簿记
     */
    @RequestMapping(value = "/exportTrade.action")
    @PreAuthorize("@ss.hasPermi('trade:otcoptiontrade:export')")
    void exportTrade(HttpServletResponse response, @RequestParam Map map) {
        startPage();
        List<Trade> list = tradeService.queryTradeDuration4OtcOptionByPage(map);
        ExcelUtil<Trade> util = new ExcelUtil<Trade>(Trade.class);
        util.exportExcel(response, list, "期权簿记");
    }

    /**
     * 导出场外持仓
     */
    @RequestMapping(value = "/exportTradeBanlance.action")
    @PreAuthorize("@ss.hasPermi('trade:otctrade:export')")
    void exportTradeBanlance(HttpServletResponse response, @RequestParam Map map) {
        startPage();
        if (StrUtil.isNotBlank(MapUtils.getString(map, "iCodes"))) {
            if (JSONUtil.parseArray(MapUtils.getString(map, "iCodes")).size() > 0) {
                map.put("iCodes", JSONUtil.parseArray(MapUtils.getString(map, "iCodes")).toArray(String.class));
            }
        }

        String instruments = MapUtils.getString(map, "instruments");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(instruments)) {
            map.put("instruments", instruments.split("\\|"));
        }

        String accIds = MapUtils.getString(map, "accIds");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(accIds)) {
            map.put("accIds", accIds.split(","));
        }

        String partyIds = MapUtils.getString(map, "partyIds");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(partyIds)) {
            map.put("partyIds", partyIds.split(","));
        }

        if (StrUtil.isNotBlank(MapUtils.getString(map, "duEventStatus"))) {
            if (JSONUtil.parseArray(MapUtils.getString(map, "duEventStatus")).size() > 0) {
                map.put("duEventStatus", JSONUtil.parseArray(MapUtils.getString(map, "duEventStatus")).toArray(String.class));
            } else {
                map.put("duEventStatus", null);
            }
        }

        if (StrUtil.isNotBlank(MapUtils.getString(map, "productTypes"))) {
            if (JSONUtil.parseArray(MapUtils.getString(map, "productTypes")).size() > 0) {
                map.put("productTypes", JSONUtil.parseArray(MapUtils.getString(map, "productTypes")).toArray(String.class));
            }else {
                map.put("productTypes", null);
            }
        }
        if (StrUtil.isNotBlank(MapUtils.getString(map, "tradeIds"))) {
            map.put("tradeIds", JSONUtil.parseArray(MapUtils.getString(map, "tradeIds")).toArray(String.class));
        }
        map.put("userId", SecurityUtils.getUserId());
        String tradeTypes = MapUtils.getString(map, "tradeTypes");
        if (StringUtils.isNotEmpty(tradeTypes)) {
            map.put("tradeTypes", tradeTypes.split(","));
        }
        List<TradeDurationDTO> list = tradeService.queryTradeDuration4OtcOptionBalanceByPage(map);
        ExcelUtil<TradeDurationDTO> util = new ExcelUtil<TradeDurationDTO>(TradeDurationDTO.class);
        util.exportExcel(response, list, "场外持仓");
    }

    /**
     * 导出场内交易
     */
    @RequestMapping(value = "/exportSimpleTrade.action")
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:export')")
    void exportSimpleTrade(HttpServletResponse response, @RequestParam Map<String, Object> param) {
        startPage();
        List<InnerTrade> list = tradeService.querySimpleTradeByPage(param);
        ExcelUtil<InnerTrade> util = new ExcelUtil<InnerTrade>(InnerTrade.class);
        util.exportExcel(response, list, "场内交易");
    }

    /**
     * 查询合约 合约下拉框
     */
    @RequestMapping(value = "/queryContract.action")
    List<Map> queryTradeContract(@RequestParam Map map) {
        map.put("userId", SecurityUtils.getUserId());
        return tradeService.queryTradeContract(map);
    }

    /**
     * 保存 提交前校验 风险和黑白名单等
     */
    @RequestMapping(value = "/checkBeforeApproval.action")
    CommResponse checkBeforeApproval(@RequestBody Trade trade) {

        return CommResponse.success("");
    }

    /**
     * 撤单前 校验
     */
    @ResponseBody
    @RequestMapping(value = "/checkRevertTrade.action")
    public Object checkRevertTrade(@RequestBody Trade trade) {
        return tradeService.checkRevertTrade(trade);
    }

    /**
     * 撤单
     */
    @ResponseBody
    @RequestMapping(value = "/revertTrade.action")
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:revert')")
    public Object revertTrade(@RequestBody Trade trade) {
        return tradeService.revertTrade(trade);
    }

    /**
     * 下载文件
     */
    @RequestMapping(value = "/downloadFile.action")
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:download')")
    public void downloadFile(HttpServletResponse response, @RequestParam  Map  param) throws UnsupportedEncodingException {
        try {
            String fileName=param.get("fileName").toString();
            String businType=param.get("businType").toString();
            //为文件名解码
            fileName = SysUtils.decode(fileName);
            fileName = fileName.replace("%20", " ");
//            String fullFilePath = new ClassPathResource("templates/simpleTemplate.xlsx").getFile().getPath();
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            Resource[] resources;
            switch (businType) {
                case "InnerTrade":
                    resources = resolver.getResources("templates/simpleTemplate.xlsx");
                    break;
                case "Vanilla":
                    resources = resolver.getResources("templates/vanillaTemplate.xlsx");
                    break;
                case "Digital":
                    resources = resolver.getResources("templates/digitalTemplate.xlsx");
                    break;
                case "DoubleDigital":
                    resources = resolver.getResources("templates/doubleDigitalTemplate.xlsx");
                    break;
                case "MultiDigital":
                    resources = resolver.getResources("templates/multiDigitalTemplate.xlsx");
                    break;
                case "Touch":
                    resources = resolver.getResources("templates/touchTemplate.xlsx");
                    break;
                case "SingleSharkFin":
                    resources = resolver.getResources("templates/sharkTemplate.xlsx");
                    break;
                case "DoubleShark":
                    resources = resolver.getResources("templates/doubleSharkTemplate.xlsx");
                    break;
                case "DoubleBarrier":
                    resources = resolver.getResources("templates/doubleBarrierTemplate.xlsx");
                    break;
                case "RangeAccrual":
                    resources = resolver.getResources("templates/rangeaccrualTemplate.xlsx");
                    break;
                case "BasicSnowball":
                    resources = resolver.getResources("templates/basicsnowballTemplate.xlsx");
                    break;
                case "Option":
                    resources = resolver.getResources("templates/OptionDigital.csv");
                    break;
                case "Must":
                    resources = resolver.getResources("templates/SharkFin.csv");
                    break;
                default:
                    resources = resolver.getResources("templates/simpleTemplate.xlsx");
            }

            final InputStream inputStream = resources[0].getInputStream();
            String suffix=".xls";
            if("Option,Must".contains(businType)){
                suffix=".csv";
            }
            File file = File.createTempFile(fileName, suffix);
            try {
                FileUtils.copyInputStreamToFile(inputStream, file);
            } finally {
                IOUtils.closeQuietly(inputStream);
            }
            response = SysUtils.downloadFile(response, file.getPath(), fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 场内交易导入
     */
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:upload')")
    @ResponseBody
    @PostMapping(value = "/uploadSimpleTradeFile.action"/*, produces = {\"text/html;charset=UTF-8\"}*/)
    public CommResponse uploadSimpleTradeFile(HttpServletRequest request, @RequestParam("file") MultipartFile file) {
        CommResponse commResponse = new CommResponse(true);
        try {
            String tradeType = "LongOpen";
            commResponse = tradeService.importTrades(request, file, tradeType);
        } catch (Exception ex) {
            ex.printStackTrace();
            commResponse.setSuccess(false);
            commResponse.setMsg("导入失败：" + ex.getMessage());
        }
        if (!commResponse.isSuccess()) {
            commResponse = (CommResponse) TransferUtil.getCacheMap().get(Thread.currentThread().getId());
            SysUtils.getErrorMsg(commResponse);
            return commResponse;
        }
        return commResponse;
    }


    /**
     * 期权簿记导入
     */
    @PreAuthorize("@ss.hasPermi('pricing:otctrade:upload')")
    @PostMapping("/uploadOtcOptionTradeFile")
    public CommResponse uploadOtcOptionTradeFile(HttpServletRequest request,MultipartFile file) {
        String uploadType = request.getParameter("uploadType");
        CommResponse commResponse = tradeService.importOtcOptionTrade(uploadType, file);
        return commResponse;
    }


    @GetMapping("/queryTtradeCountByAccId.action")
    public int queryTtradeCountByAccId(@RequestParam String accId) {
        return tradeService.queryTtradeCountByAccId(accId);
    }
}
